/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ecom.shell.commandsImpl;

import ecom.beans.EcomAdminRemote;
import ecom.beans.EcomCustomerRemote;
import ecom.beans.UserBean;
import ecom.beans.exception.DeviseException;
import ecom.shell.commandsImpl.OutputCommandImpl.Outputs;
import ecom.shell.exception.InsuffisantPrivilegeException;
import java.io.IOException;
import java.io.PrintStream;
import java.io.StringWriter;
import java.text.DecimalFormat;
import java.util.HashSet;
import java.util.Set;
import java.util.StringTokenizer;
import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
import shell.ShellCommand;
import shell.ShellContext;

public class UserCommandImpl implements ShellCommand {

    private ShellContext _context = null;

    public UserCommandImpl(ShellContext context) {
        _context = context;
    }

    @Override
    public String getName() {
        return "user";
    }

    @Override
    public String getUsage() {
        return "user";
    }

    @Override
    public String getShortDescription() {
        String commands = "User commands\n";
        commands += "\t-help ............................................................................................get user commands description\n";
        if (true == _context.getVar("isAdmin")) {
            commands += "\t[without arg] ....................................................................................get all users\n";
        }
        commands += "\t-add [pseudo] [password] [email] [adress with '_'] [postalCode] [city] [country] [currency] [tel] [iban]........create a user\n";
        commands += "\t-remove [pseudo] [password] ....................................................................................delete an user\n";
        commands += "\t-user [pseudo] [password] ......................................................................................display specified user details\n";
        return commands;
    }

    @Override
    public String execute(String cmdline, PrintStream out, PrintStream err) throws InsuffisantPrivilegeException {
        StringBuilder result = new StringBuilder();
        EcomCustomerRemote ecomCustomerBean = (EcomCustomerRemote) _context.getVar("customerBean");
        EcomAdminRemote ecomAdminBean = (EcomAdminRemote) _context.getVar("adminBean");
        Outputs currentOutput = (Outputs) _context.getVar("output");
        String currentCurrency = (String) _context.getVar("currency");
        Set<UserBean> userList = null;
        StringTokenizer cmd = new StringTokenizer(cmdline, " ");
        cmd.nextToken();

        if (cmd.countTokens() == 0) {
            if (true != _context.getVar("isAdmin")) {
                throw new InsuffisantPrivilegeException();
            }
            userList = ecomAdminBean.getAllUsers();
            try {
                return getStringList(ecomCustomerBean, out, userList, currentOutput, currentCurrency);
            } catch (Exception ex) {
                System.out.println("Error with getting all users : " + ex.getMessage());
            }
        } else {
            String option = cmd.nextToken();

            if (option.equals("-help")) {
                result.append(getShortDescription());
            } else if (option.equals("-add")) {
                if (true != _context.getVar("isAdmin")) {
                    throw new InsuffisantPrivilegeException();
                }
                if (cmd.countTokens() == 10) {
                    try {
                        String pseudo = cmd.nextToken();
                        String password = cmd.nextToken();
                        String email = cmd.nextToken();
                        String adress = cmd.nextToken();
                        adress = adress.replace("_", " ");
                        String postalCode = cmd.nextToken();
                        String city = cmd.nextToken();
                        String country = cmd.nextToken();
                        String currency = cmd.nextToken();
                        String tel = cmd.nextToken();
                        String iban = cmd.nextToken();
                        boolean isAdmin = false;
                        if (true == _context.getVar("isAdmin")) {
                            isAdmin = true;
                        }
                        Long idUser = ecomAdminBean.createUser(pseudo, password, email, adress, postalCode, city, country, currency, tel, isAdmin, iban, new Double(0));
                        result.append("User created with id : ").append(idUser);
                    } catch (Exception ex) {
                        err.println("Error with user creation : " + ex.getMessage());
                    }
                } else {
                    err.println(EcomCommandsConstantes.INCORRECT_NUMBER_ARGS);
                }
            } else if (option.equals("-remove")) {
                if (cmd.countTokens() == 2) {
                    try {
                        String pseudo = cmd.nextToken();
                        String password = cmd.nextToken();
                        ecomAdminBean.removeUser(pseudo, password);
                        result.append("User pseudo : ").append(pseudo).append(" deleted");
                    } catch (Exception ex) {
                        err.println("Error with user deletion : " + ex.getMessage());
                    }
                } else {
                    err.println(EcomCommandsConstantes.INCORRECT_NUMBER_ARGS);
                }
            } else if (option.equals("-user")) {
                if (cmd.countTokens() == 2) {
                    try {
                        String pseudo = cmd.nextToken();
                        String password = cmd.nextToken();
                        UserBean user = ecomCustomerBean.getUserByPseudoAndPassword(pseudo, password);
                        return getTextAccount(ecomCustomerBean, out, user, currentOutput, currentCurrency);
                    } catch (Exception e) {
                        err.println("Error with user detail : " + e.getMessage());
                    }
                } else {
                    err.println(EcomCommandsConstantes.INCORRECT_NUMBER_ARGS);
                }
            } else {
                err.println(option + " is not known for Account Management");
            }
        }
        return result.toString();
    }

    private String getStringList(EcomCustomerRemote ecomCustomerBean, PrintStream out, Set<UserBean> userList, Outputs currentOutput, String currentCurrency) throws DeviseException, IOException {
        StringBuilder res = new StringBuilder();
        if (currentOutput.equals(Outputs.XML)) {
            Element users = new Element("users");
            org.jdom.Document document = new Document(users);

            for (UserBean a : userList) {
                users.addContent(createXMLNode(a, ecomCustomerBean, true, currentCurrency));
            }
            XMLOutputter sortie = new XMLOutputter(Format.getPrettyFormat());
            res.append(sortie.outputString(document));
        } else if (currentOutput.equals(Outputs.TEXT)) {
            for (UserBean a : userList) {
                res.append(getText(out, a, ecomCustomerBean, currentCurrency)).append("\n");
            }
        }  else {
            res.append("Output format '").append(currentOutput).append("' is not implementing for this command");
        }
        return res.toString();
    }

    private String getTextAccount(EcomCustomerRemote ecomCustomerBean, PrintStream out, UserBean a, Outputs currentOutput, String currentCurrency) throws DeviseException, IOException {
        Set<UserBean> list = new HashSet<UserBean>();
        list.add(a);
        return getStringList(ecomCustomerBean, out, list, currentOutput, currentCurrency);
    }

    private String getText(PrintStream out, UserBean user, EcomCustomerRemote ecomCustomerBean, String currentCurrency) {
        return (user.toString() + " IN " + currentCurrency);
    }

    private Element createXMLNode(UserBean a, EcomCustomerRemote ecomCustomerBean, boolean withAccount, String currentCurrency) throws DeviseException {
        Element user = new Element("user");
        Attribute id = new Attribute("id", String.valueOf(a.getIdUser()));
        user.setAttribute(id);

        Element pseudo = new Element("pseudo");
        pseudo.setText(a.getPassword());
        user.addContent(pseudo);

        Element password = new Element("password");
        password.setText(a.getPassword());
        user.addContent(password);

        Element email = new Element("email");
        email.setText(a.getEmail());
        user.addContent(email);

        Element adress = new Element("adress");
        adress.setText(a.getAdress());
        user.addContent(adress);

        Element postalCode = new Element("postal_code");
        postalCode.setText(a.getPostalCode());
        user.addContent(postalCode);

        Element city = new Element("city");
        city.setText(a.getCity());
        user.addContent(city);

        Element tel = new Element("tel");
        tel.setText(a.getTel());
        user.addContent(tel);

        Element currencyElement = new Element("currency");
        currencyElement.setText(a.getCurrency());
        user.addContent(currencyElement);

        Element isAdmin = new Element("is_admin");
        isAdmin.setText(a.getIsAdmin() ? "true" : "false");
        user.addContent(isAdmin);

        if (withAccount) {
            Element account = new Element("account");
            Attribute accountId = new Attribute("id", String.valueOf(a.getAccount().getIban()));
            account.setAttribute(accountId);
            user.addContent(account);

            Element balance = new Element("balance");
            DecimalFormat myFormatter = new DecimalFormat("##0.00");
            balance.setText(myFormatter.format(ecomCustomerBean.convertFromEuro(a.getAccount().getBalance(), currentCurrency)));
            Attribute currency = new Attribute("currency", currentCurrency);
            balance.setAttribute(currency);
            account.addContent(balance);
        }
        return user;
    }

  }
